#ifndef LINUX_SERIAL_SERIAL_PORT_H
#define LINUX_SERIAL_SERIAL_PORT_H

#include <termios.h>

// 波特率
enum EBaudRate
{
    BR1200 = 0,
    BR2400,
    BR4800,
    BR9600,
    BR19200,
    BR38400,
    BR57600,
    BR115200,
    BR230400,
    BR460800,
    BR921600
};

// 数据位
enum EDataBits
{
    DB5 = 0,
    DB6,
    DB7,
    DB8
};

// 流控制
enum EFlowControl
{
    NoFlowControl = 0,  // 不使用流控
    CtsRtsFlowControl,  // 硬流控
    XonXoffFlowControl  // 软流控
};
// 校验位
enum EParity
{
    NoParity = 0,   // 不使用校验
    OddParity,      // 奇校验
    EvenParity      // 偶校验
};
// 停止位
enum EStopBits
{
    OneStopBit = 0,
    TwoStopBits
};

// 串口类
class CSerialPort
{
public:
    // 使用默认实现的成员函数
    CSerialPort(): handle_(-1), timeout_(0), baud_rate_(BR115200), data_bits_(DB8),
                   parity_(NoParity), stop_bits_(OneStopBit), flow_control_(NoFlowControl) {}
    ~CSerialPort() = default;
    CSerialPort& operator= (const CSerialPort& self) = delete;
    CSerialPort(const CSerialPort& self) = delete;
    // 自定义成员函数
    // 打开串口
    int open(const char* port, EBaudRate baud = BR9600, EDataBits data = DB8, EParity pari = NoParity,
             EStopBits stop = OneStopBit, EFlowControl flow = NoFlowControl, int time = -1);
    // 关闭串口
    void close();
    // 串口是否打开
    bool is_open() const;
    // 接收数据
    long receive(void* buff, int len) const;
    // 发送数据
    void send(const void* buff, long buffer_len) const;
protected:
    // 自定义串口设置函数
    // 取得串口属性
    inline void get_attribute(struct termios* attr) const;
    // 设置串口属性
    inline void set_attribute(const struct termios* attr) const;

    // 以下属性的修改，可以在打开串口后使用，但是为了保证接口的简单可用，
    // 所以屏蔽掉了以下接口，可以在需要使用的时候设置成public属性
    // 设置波特率
    void set_baud_rate(EBaudRate baud);
    // 设置数据位
    void set_data_bits(EDataBits data);
    // 设置校验位
    void set_parity(EParity pari);
    // 设置停止位
    void set_stop_bits(EStopBits stop);
    // 设置数据流控制
    void set_flow_control(EFlowControl flow);
    // 设置接收超时
    void set_timeout(int time);
private:
    // 自定义成员函数，清除了所有属性信息，谨慎使用
    void set_normal_mode();

    // 成员变量
    int     handle_;      // 串口句柄
    int     timeout_;     // -1: 阻塞模式，0: 非阻塞模式，>0: 超时
    EBaudRate       baud_rate_;    // 波特率
    EDataBits       data_bits_;    // 数据位
    EParity         parity_;      // 校验位
    EStopBits       stop_bits_;    // 停止位
    EFlowControl    flow_control_; // 数据流控制
};

#endif //LINUX_SERIAL_SERIAL_PORT_H
